1 Introducción


1.1 Presentación

Esta práctica cubre de forma transversal la asignatura.

Las Prácticas 1 y 2 de la asignatura se plantean de una forma conjunta de modo que la Práctica 2 será continuación de la 1.

El objetivo global de las dos prácticas consiste en seleccionar uno o varios juegos de datos, realizar las tareas de preparación y análisis exploratorio con el objetivo de disponer de datos listos para aplicar algoritmos de clustering, asociación y clasificación.

1.2 Competencias

Las competencias que se trabajan en esta prueba son:

  • Uso y aplicación de las TIC en el ámbito académico y profesional.
  • Capacidad para innovar y generar nuevas ideas.
  • Capacidad para evaluar soluciones tecnológicas y elaborar propuestas de proyectos teniendo en cuenta los recursos, las alternativas disponibles y las condiciones de mercado.
  • Conocer las tecnologías de comunicaciones actuales y emergentes así como saberlas aplicar convenientemente para diseñar y desarrollar soluciones basadas en sistemas y tecnologías de la información.
  • Aplicación de las técnicas específicas de ingeniería del software en las diferentes etapas del ciclo de vida de un proyecto.
  • Capacidad para aplicar las técnicas específicas de tratamiento, almacenamiento y administración de datos.
  • Capacidad para proponer y evaluar diferentes alternativas tecnológicas para resolver un problema concreto.

1.3 Objetivos

La correcta asimilación de todos los aspectos trabajados durante el semestre.
En esta práctica abordamos un caso real de minería de datos donde tenemos que poner en juego todos los conceptos trabajados. Hay que trabajar todo el ciclo de vida del proyecto. Desde el objetivo del proyecto hasta la implementación del conocimiento encontrado pasando por la preparación, limpieza de los datos, conocimiento de los datos, generación del modelo, interpretación y evaluación.

1.4 Descripción de la PRA a realizar

1.5 Recursos Básicos

Material docente proporcionado por la UOC.

1.6 Criterios de valoración

Ejercicios prácticos

Para todas las PRA es necesario documentar en cada apartado del ejercicio práctico que se ha hecho y como se ha hecho.

1.7 Formato y fecha de entrega PRA_1

El formato de entrega es: usernameestudiant-PRAn.html/doc/docx/odt/pdf
Fecha de entrega: 02/12/2020
Se debe entregar la PRA_1 en el buzón de entregas del aula

1.8 Nota: Propiedad intelectual

A menudo es inevitable, al producir una obra multimedia, hacer uso de recursos creados por terceras personas. Es por lo tanto comprensible hacerlo en el marco de una práctica de los estudios de Informática, Multimedia y Telecomunicación de la UOC, siempre y cuando esto se documente claramente y no suponga plagio en la práctica.

Por lo tanto, al presentar una práctica que haga uso de recursos ajenos, se debe presentar junto con ella un documento en que se detallen todos ellos, especificando el nombre de cada recurso, su autor, el lugar donde se obtuvo y su estatus legal: si la obra esta protegida por el copyright o se acoge a alguna otra licencia de uso (Creative Commons, licencia GNU, GPL …). El estudiante deberá asegurarse de que la licencia no impide específicamente su uso en el marco de la práctica. En caso de no encontrar la información correspondiente tendrá que asumir que la obra esta protegida por copyright.

Deberéis, además, adjuntar los ficheros originales cuando las obras utilizadas sean digitales, y su código fuente si corresponde.


2 Enunciado


Todo estudio analítico debe nacer de una necesidad por parte del negocio o de una voluntad de dotarle de un conocimiento contenido en los datos y que solo podremos obtener a través de una colección de buenas prácticas basadas en la Minería de Datos.

El mundo de la analítica de datos se sustenta en 3 ejes:

  1. Uno de ellos es el profundo conocimiento que deberíamos tener del negocio al que tratamos de dar respuestas mediante los estudios analíticos.

  2. El otro gran eje es sin duda las capacidades analíticas que seamos capaces de desplegar y en este sentido, las dos prácticas de esta asignatura pretenden que el estudiante realice un recorrido sólido por este segundo eje.

  3. El tercer eje son los Datos. Las necesidades del Negocio deben concretarse con preguntas analíticas que a su vez sean viables responder a partir de los datos de que disponemos. La tarea de analizar los datos es sin duda importante, pero la tarea de identificarlos y obtenerlos va a ser para un analista un reto permanente.

Como primera parte del estudio analítico que nos disponemos a realizar, se pide al estudiante que complete los siguientes pasos:

  1. Seleccionar un juego de datos y justificar su elección. El juego de datos deberá tener capacidades para que se le puedan aplicar algoritmos supervisados, algoritmos no supervisados y reglas de asociación.

  2. Realizar un análisis exploratorio del juego de datos seleccionado.

  3. Realizar tareas de limpieza y acondicionado para poder ser usado en procesos de modelado.

  4. Realizar métodos de discretización

  5. Aplicar un estudio PCA sobre el juego de datos. A pesar de no estar explicado en el material didáctico, se valorará si en lugar de PCA investigáis por vuestra cuenta y aplicáis SVD (Single Value Decomposition).


3 Solución


3.1 Introducción

En esta práctica se realizará una simulación de un proyecto real de minería de datos. El juego de datos seleccionado será la base para recorrer todo el ciclo de vida del proyecto, pasando por la limpieza y preparación de los datos hasta la obtención del conocimiento, resultado obtenido de la aplicación de los diferentes algoritmos de ML.

En esta primera parte, solamente se realizarán las tares relacionadas con la preparación de los datos, aplicando las diferentes técnicas estudiadas en clase, tales como la normalización, la discretización y el tratamiento de outliers y missing data. De manera que manera los datos quedarán listos para que en la segunda parte de la práctica se le puedan aplicar los diferentes algoritmos. En esta práctica también se aplicará una técnica de reducción de dimensionalidad al dataset SVD (Single Value Decomposition ), esto como resultado de la investigación autodidacta de este tipo de técnicas.

3.2 Elección del dataset

Para elegir el conjunto de datos se ha consultado la plataforma Kaggle, de la que se ha seleccionado el conjunto de datos Pima Indians Diabetes Database.

Este conjunto de datos contiene información relacionada con pacientes del " National Institute of Diabetes and Digestive and Kidney Diseases " de los Estados Unidos, en el se recogen valores de algunas variables médicas con el objetivo de predecir si una persona tiene o no Diabetes, según la descripción del conjunto de datos la mayoría de los pacientes son mujeres mayores de 21 años. A continuación se describen cada una de estas variables predictoras y la variable objetivo.

  • Pregnancies: Número de veces que estuvo embarazada.
  • Glucose: Concentración de Glucosa en sangre.
  • BloodPressure: Presión arterial diastólica.
  • SkinThickness: Espesor del pliegue cutáneo del tríceps.
  • Insulin: Nivel de Insulina sérica de 2 horas.
  • BMI: ïndice de masa corporal.
  • DiabetesPedigreeFunction: Función del pedigrí de la diabetes.
  • Age: Edad del paciente.
  • Outcome: variable objetivo, está formada por dos clases, “0” => “Diabetic” …. “1” => “Healthy”

Este juego de datos ha sido seleccionado después de realizar una larga búsqueda por varios de los repositorios de datos abiertos, su elección está principalmente fundamentada por las capacidades analíticas que se intuyen de los datos y porque cumple a la perfección con los requerimientos indicados en la orientación de la práctica. A este juego de datos se le pueden aplicar algoritmos supervisados, no supervisados y reglas de asociación, y los datos están en un formato que facilitan estas tareas.

Por ejemplo para aplicar algoritmos supervisados se pueden separar los datos en dos partes, las variables predictoras por una lado y la objetivo por otra. Se le pueden aplicar cualquiera de los algoritmos de agrupamiento estudiados en clase.

Con respecto a la clasificación, este dataset también puede ser empleado en la construcción de un modelo válido, solamente sería necesario dividir el conjunto en las partes (después de la limpieza y preparación) de training y testing, y de esta manera poder evaluar evaluar el modelo con los diferentes algoritmos.

Y finalmente, en cuanto a als reglas de asociación, este dataset también puede ser empleado para tareas de este tipo, aunque todas sus variables sean numéricas se puede optar por discretizarlas o simplemente aplicar las reglas y obtener los diferentes rangos de las variables predictoras.

3.3 Carga de los Datos

A continuación se procede a la carga de los datos, el dataset fue previamente descargado al entorno local y colocado en el directorio data, que cuelga del directorio principal del proyecto. También se obtendrá una vista panorámica de los datos, principalmente para comprobar el formato de estos, su tamaño y su dimensionalidad.

library(plotly)

# Loading the data file.
diabetes.raw <- read.csv("./data/diabetes.csv", header = TRUE)

3.4 Visión General del Dataset

Para tener una primera idea de como está conformado el dataset es necesario realizar una primera exploración de sus características generales.

# Getting the structure of the data set.
str(diabetes.raw)
## 'data.frame':    768 obs. of  9 variables:
##  $ Pregnancies             : int  6 1 8 1 0 5 3 10 2 8 ...
##  $ Glucose                 : int  148 85 183 89 137 116 78 115 197 125 ...
##  $ BloodPressure           : int  72 66 64 66 40 74 50 0 70 96 ...
##  $ SkinThickness           : int  35 29 0 23 35 0 32 0 45 0 ...
##  $ Insulin                 : int  0 0 0 94 168 0 88 0 543 0 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 43.1 25.6 31 35.3 30.5 0 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 2.288 ...
##  $ Age                     : int  50 31 32 21 33 30 26 29 53 54 ...
##  $ Outcome                 : int  1 0 1 0 1 0 1 0 1 1 ...
# Looking basics info of the attributes. 
summary(diabetes.raw)
##   Pregnancies        Glucose      BloodPressure    SkinThickness  
##  Min.   : 0.000   Min.   :  0.0   Min.   :  0.00   Min.   : 0.00  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 62.00   1st Qu.: 0.00  
##  Median : 3.000   Median :117.0   Median : 72.00   Median :23.00  
##  Mean   : 3.845   Mean   :120.9   Mean   : 69.11   Mean   :20.54  
##  3rd Qu.: 6.000   3rd Qu.:140.2   3rd Qu.: 80.00   3rd Qu.:32.00  
##  Max.   :17.000   Max.   :199.0   Max.   :122.00   Max.   :99.00  
##     Insulin           BMI        DiabetesPedigreeFunction      Age       
##  Min.   :  0.0   Min.   : 0.00   Min.   :0.0780           Min.   :21.00  
##  1st Qu.:  0.0   1st Qu.:27.30   1st Qu.:0.2437           1st Qu.:24.00  
##  Median : 30.5   Median :32.00   Median :0.3725           Median :29.00  
##  Mean   : 79.8   Mean   :31.99   Mean   :0.4719           Mean   :33.24  
##  3rd Qu.:127.2   3rd Qu.:36.60   3rd Qu.:0.6262           3rd Qu.:41.00  
##  Max.   :846.0   Max.   :67.10   Max.   :2.4200           Max.   :81.00  
##     Outcome     
##  Min.   :0.000  
##  1st Qu.:0.000  
##  Median :0.000  
##  Mean   :0.349  
##  3rd Qu.:1.000  
##  Max.   :1.000
# Looking a panoramic view of the data.
head(diabetes.raw)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35       0 33.6
## 2           1      85            66            29       0 26.6
## 3           8     183            64             0       0 23.3
## 4           1      89            66            23      94 28.1
## 5           0     137            40            35     168 43.1
## 6           5     116            74             0       0 25.6
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 5                    2.288  33       1
## 6                    0.201  30       0

3.5 Visualización general del Dataset

Antes de proceder a manipular los datos se realiza un análisis visual de las variables predictoras del conjunto de datos. Como los datos están en formato numérico se utilizan histogramas para representarlos, el objetivo de este análisis es complementar el análisis realizado anteriormente en el que se observaron las principales características de los datos, tales como: formato, dimensionalidad y tipo.

La función visual_analy() se encarga de crear la representación visual de todas las variables a la vez, esta función será utilizada en varios puntos del proyecto para comprobar el estado de los datos.

visual_analy <- function(df){
  
# Create a empty list for plots.
plot_lys <- list()

# Get the names of all varibales in the raw data set.
names <- colnames(df[1:8])

# Fill a plots's list with plot_ly histograms.
for (i in 1:length(names)){
  
  fig <- plot_ly(x = df[,i],
                 type = "histogram",
                 histnorm = "count",
                 name = names[i])
  
  plot_lys[[i]] <- fig
}

# Create a subplot with each plot in the list.
repres <- subplot(plot_lys, nrows = 2)
repres

}

Inicialmente se realiza el análisis visual a los datos originales.

# Visual Analysis
visual_analy(diabetes.raw)

3.6 Conclusiones del análisis inicial

De este primer análisis se obtienen las siguientes conclusiones.

  • Se aprecia que contiene 768 observaciones de las 9 variables descritas anteriormente.
  • Los datos están en formato numérico, la mayoría son de tipo int a excepción de los valores de BMI y de DiabetesPedigreeFunction que son de tipo num.
  • Los valores están en diferentes escalas, por ejemplo entre los valores de la edad ( age ) y los del nivel de glucosa en sangre ( Glucose ) hay una diferencia significativa.
  • Se aprecian algunos valores “cero” en los datos, algunos de ellos parecen ser outliers.

3.7 Preparación y Limpieza de los datos

En este apartado se realizarán todas las modificaciones necesarias para mejorar la calidad de los datos, poniendo especial interés en el tratamiento a los valores ausentes y a los valores extremos.

El primer paso que se realiza es crear una copia de los datos originales, en esta copia se almacenan los datos durante todo el proceso de preparación y limpieza.

# Create a copy for cleaned data.
diabetes.cl <- diabetes.raw

3.7.1 Valores Extremos

De la gráfica mostrada en el apartado de Visualicación Inicial del Datset se intuye que existen algunos valores que pueden ser clasificados como outliers, como por ejemplo el valor de una paciente que muestra que estuvo embarazada 17 veces, o los valores del índice de masa corporal cercano a cero, estos valores a simple vista parecen extraños con respecto a los valores de su muestra. Por este motivo será necesario realizar un análisis de cada una de las variables que componen el dataset para detectar los valores extremos y tratarlos según convenga.

Para facilitar el trabajo en la búsqueda de outliers se crea la función check_values(), que recibirá como parámetro la variable que se desea analizar y devuelve un gráfico Box Plot y los valores de los posibles outlilers.

En cada caja de gráfico se muestra la siguiente información estadística de cada variable:

  • Mediana: Valor medio del dataset (Q2/50th Percentile).
  • Primer Quartil: Valor medio entre el valor mínimo y la mediana (Q1/25th Percentile).
  • Tercer Quartil: Valor medio entre la mediana y el valor máximo (Q3/75th Percentile).
  • InterQuartil: (IQR): Rango entre el Q1 y el Q3, determina cuan separados están los valores centrales del dataset.
  • Valor máximo: Q3 + 1.5xIQR
  • Valor Mínimo: Q1 -1.5xIQR
  • Outliers: Se ubican por fuera de los límites de los wiskers.

Además de esta información, el gráfico se divide en cuatro partes más, mostrando una caja con información referente a los siguientes tipos.

  • Todos los puntos de la variable.
  • Solo los Wiskers.
  • Solo los posibles outiliers.
  • Wiskers y outliers.
check_values <- function(feature){

fig <- plot_ly(type = 'box')
fig <- fig %>% add_boxplot(y = feature,
                           jitter = 0.3, 
                           pointpos = -1.8, 
                           boxpoints = 'all',
                           marker = list(color = 'rgb(7,40,89)'),
                           line = list(color = 'rgb(7,40,89)'),
                           name = "All Points")

fig <- fig %>% add_boxplot(y = feature, 
                           name = "Only Whiskers", 
                           boxpoints = FALSE,
                           marker = list(color = 'rgb(9,56,125)'),
                           line = list(color = 'rgb(9,56,125)'))

fig <- fig %>% add_boxplot(y = feature, 
                           name = "Suspected Outlier",
                           boxpoints = 'suspectedoutliers',
                           marker = list(color = 'rgb(8,81,156)',
                           outliercolor = 'rgba(219, 64, 82, 0.6)',
                           line = list(outliercolor = 'rgba(219, 64, 82, 1.0)',
                                        outlierwidth = 2)),
                           line = list(color = 'rgb(8,81,156)'))

fig <- fig %>% add_boxplot(y = feature,
                           name = "Whiskers and Outliers", 
                           boxpoints = 'outliers',
                           marker = list(color = 'rgb(107,174,214)'),
                           line = list(color = 'rgb(107,174,214)'))

fig <- fig %>% layout(title = "Box Plot Indentifying Outliers")

# Get the posibles outliers.
outliers <- boxplot.stats(feature)$out


return(list(fig=fig,out=outliers))
}

Se efectúa la búsqueda de outliers en cada una de las variables del dataset. En los casos en los que se considera necesario se eliminan los registros del conjunto de datos.

3.7.1.1 Pregnancies

# Get the results of the analysis.
values = check_values(diabetes.cl$Pregnancies)

# Boxplot figure.
values$fig
# Outliers.
values$out
## [1] 15 17 14 14
# Deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$Pregnancies %in% values$out),]

# Check the result of deleting process.
values <- check_values(diabetes.cl$Pregnancies)
values$fig

3.7.1.2 Glucose

# Get the results of the analysis.
values = check_values(diabetes.cl$Glucose)

# Boxplot figure.
values$fig
# Outliers.
values$out
## [1] 0 0 0 0 0

En los valores de la glucosa no se detectan outliers.

3.7.1.3 BloodPressure

# Get the results of the analysis.
values = check_values(diabetes.cl$BloodPressure)

# Boxplot figure.
values$fig
# Outliers.
values$out
##  [1]   0   0  30 110   0   0   0   0 108 122  30   0 110   0   0   0   0   0   0
## [20]   0   0   0   0 108   0   0   0   0   0   0   0   0   0   0 110   0  24   0
## [39]   0   0   0 114   0   0   0
# Deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$BloodPressure %in% values$out),]

# Check the result of deleting process.
values <-check_values(diabetes.cl$BloodPressure)
values$fig

3.7.1.4 SkinThickness

# Get the results of the analysis.
values = check_values(diabetes.cl$SkinThickness)

# Boxplot figure
values$fig
# Outliers
values$out
## [1] 99
# deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$SkinThickness %in% values$out),]

# Check the result of deleting process.
values <- check_values(diabetes.cl$SkinThickness)
values$fig

3.7.1.5 Insulin

# Get the results of the analysis.
values = check_values(diabetes.cl$Insulin)

# Boxplot figure
values$fig
# Outliers
values$out
##  [1] 543 846 342 495 485 495 478 744 370 680 402 375 545 360 465 415 579 474 328
## [20] 480 326 330 600 440 540 480 335 387 392 510
# deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$Insulin %in% values$out),]

# Check the result of deleting process.
values <- check_values(diabetes.cl$Insulin)
values$fig

3.7.1.6 BMI

# Get the results of the analysis.
values = check_values(diabetes.cl$BMI)

# Boxplot figure
values$fig
# Outliers
values$out
## [1]  0.0 53.2  0.0 50.0 52.9  0.0 59.4 57.3  0.0
# deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$BMI %in% values$out),]

# Check the result of deleting process.
values <- check_values(diabetes.cl$BMI)
values$fig

3.7.1.7 DiabetesPedigreeFunction

# Get the results of the analysis.
values = check_values(diabetes.cl$DiabetesPedigreeFunction)

# Boxplot figure
values$fig
# Outliers
values$out
##  [1] 2.288 1.441 1.390 1.893 1.781 1.222 1.400 1.189 1.321 1.224 1.318 1.213
## [13] 1.353 1.224 1.391 1.476 1.268 1.600 1.191 1.251 1.699 1.258 1.282 1.698
## [25] 1.461 1.292 1.394 1.174 1.182
# deleting the outliers.
diabetes.cl <- diabetes.cl[-which(diabetes.cl$DiabetesPedigreeFunction %in% values$out),]

# Check the result of deleting process.
values <- check_values(diabetes.cl$DiabetesPedigreeFunction)
values$fig

3.7.1.8 Age

# Get the results of the analysis.
values = check_values(diabetes.cl$Age)

# Boxplot figure
values$fig
# Outliers
values$out
##  [1] 69 65 66 65 67 81 67 66 67 66 70 68 66

En el caso de la edad aunque estadísticamente estos valores sean outliers no se eliminarán porque son edades razonables, es decir, que incluso la edad con valor de 81 años es una edad común entre la población.

3.7.2 Identificación de missing values

De manera similar a la ocurrida con los outliers en el apartado Visualicación Inicial del Datset también se han identificado algunos valores que pueden corresponder a missing values. Más específicamente se han detectado una gran cantidad de 0 “ceros” en los datos, principalmente en las variables " Insulin" y " SkinThickness".

Al analizar un poco más en profundidad estas variables se detecta que sus valores no pueden ser cero, es imposible que los valores de glucosa de una persona sean cero, o igualmente que los niveles de insulina después de dos horas sea cero, con lo cual estos valores demuestran que corresponden a valores nulos. Por ende se procede a establecerlos como NaN, para facilitar su posterior tratamiento, destacar que no se sustituyen en todas las variables, ya que en algunas si es posible que el cero sea una medida válida, como por ejemplo en la variable " Pregnancies", que indica la cantidad de embarazos de las mujeres.

# Replace 0s with Nan.
nan_names <- c('Glucose','BloodPressure','SkinThickness','Insulin','BMI')

diabetes.cl[nan_names][diabetes.cl[nan_names] == 0] <- NaN

# Looking a panoramic view of the data.
head(diabetes.cl)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35     NaN 33.6
## 2           1      85            66            29     NaN 26.6
## 3           8     183            64           NaN     NaN 23.3
## 4           1      89            66            23      94 28.1
## 6           5     116            74           NaN     NaN 25.6
## 7           3      78            50            32      88 31.0
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 6                    0.201  30       0
## 7                    0.248  26       1

3.7.3 Tratamiento de los missing values

Para seleccionar la manera más adecuada de tratar los valores ausentes es necesario realizar algunas pruebas, estas pruebas permiten conocer algunas características de estos valores, y al final del proceso los resultados de estas pruebas serán definitorios a la hora de elegir un método para tratar los missing values.

Inicialmente se cuentan los missing values por cada variable. Y se calcula el porcentaje que representan estos valores del total de entradas en el conjunto de datos.

# Amount of NaN values per each column.
colSums(is.na(diabetes.cl))
##              Pregnancies                  Glucose            BloodPressure 
##                        0                        5                        0 
##            SkinThickness                  Insulin                      BMI 
##                      182                      314                        0 
## DiabetesPedigreeFunction                      Age                  Outcome 
##                        0                        0                        0
# Percercent of null values.
perc <- (sum(is.na(diabetes.cl$SkinThickness)))/nrow(diabetes.cl)*100
paste("Porciento de valores nulos en SkinThickness:", round(perc,2))
## [1] "Porciento de valores nulos en SkinThickness: 28"
perc <- (sum(is.na(diabetes.cl$Insulin)))/nrow(diabetes.cl)*100
paste("Porciento de valores nulos en Insulin:", round(perc,2))
## [1] "Porciento de valores nulos en Insulin: 48.31"

Como se puede apreciar en el anterior análisis un gran porciento de los datos contiene missin values, llegando a alcanzar el 48% en el caso de la variable Insulin, con lo cual el método para tratar estos datos debe ser elegido con cuidado. Será necesario continuar con el análisis de estos valores para tomar una decisión.

Partiendo de la base de que la variable Insulin es la que mayor porcentaje de missing valeus tiene, se calcula la proporción de los valores nulos de SkinThickness que también son valores nulos en Insulin.

# Get the matches in null values in both variables.
sum((is.na(diabetes.cl$SkinThickness)) & (is.na(diabetes.cl$Insulin)))
## [1] 182

El análisis anterior muestra que todos lo valores nulos de la variable SkinThickness también lo son en la variable Insulin, lo que demuestra que estos registros presentan serios problemas. Puede ser porque no fueron tomados por los doctores en el momento de hacer el estudio,o porque solo tomaban las muestras de las personas que pensaban que podían presentar la enfermedad.

Se evalúan las correlaciones de esta variable con la variable objetivo para ver que influencia tienen estos valores en la predicción.

# Get the correlation with target variable.
cor.test(diabetes.cl$Insulin, diabetes.raw$Outcome[diabetes.cl$Insulin])
## 
##  Pearson's product-moment correlation
## 
## data:  diabetes.cl$Insulin and diabetes.raw$Outcome[diabetes.cl$Insulin]
## t = 2.8276, df = 334, p-value = 0.004973
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  0.04666807 0.25570989
## sample estimates:
##       cor 
## 0.1528989
cor.test(diabetes.cl$SkinThickness, diabetes.raw$Outcome[diabetes.cl$SkinThickness])
## 
##  Pearson's product-moment correlation
## 
## data:  diabetes.cl$SkinThickness and diabetes.raw$Outcome[diabetes.cl$SkinThickness]
## t = -5.0493, df = 466, p-value = 6.373e-07
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
##  -0.3119581 -0.1400051
## sample estimates:
##        cor 
## -0.2277565

Como se puede apreciar los valores de las correlaciones no son muy altos, con lo cuál estas variables no tienen una gran influencia en la variable objetivo.

Este hecho ayuda a tomar la decisión de sustituir todos los registros que contengan valores nulos, Se seleccionará el valor de la mediana de cada una de las variables que contengan valores ausentes para la sustitución.

Inicialmente se había analizado la opción de eliminar estos datos, pero esto trae consigo una pérdida de datos muy significativa para el modelo, ya que hubiese sido necesario eliminar casi el 50% de los datos, y se perdería la capacidad predictora de las demás variables. Es cierto que al sustituir estos valores por los de la mediana se introducen muchos datos al modelo, y esto puede acarrear un sesgo en la información, pero es una solución mejor que la de eliminarlos. Además los datos de las medianas en estos casos son valores que pueden ser considerados normales, ya que corresponden a valores de personas sanas en estas pruebas.

3.7.4 Tratando los missin values

Tal y como se había expresado anteriormente, se procede a remplazar los missing vlaues por el valor de la mediana de cada un de sus variables.

# Replace the values with the median value.
for(i in 1:ncol(diabetes.cl)){
  diabetes.cl[is.na(diabetes.cl[,i]), i] <- median(diabetes.cl[,i], na.rm = TRUE)
}

# Getting the structure of the data set.
str(diabetes.cl)
## 'data.frame':    650 obs. of  9 variables:
##  $ Pregnancies             : int  6 1 8 1 5 3 4 10 5 0 ...
##  $ Glucose                 : num  148 85 183 89 116 78 110 168 166 118 ...
##  $ BloodPressure           : int  72 66 64 66 74 50 92 74 72 84 ...
##  $ SkinThickness           : num  35 29 29 23 29 32 29 29 19 47 ...
##  $ Insulin                 : num  116 116 116 94 116 ...
##  $ BMI                     : num  33.6 26.6 23.3 28.1 25.6 31 37.6 38 25.8 45.8 ...
##  $ DiabetesPedigreeFunction: num  0.627 0.351 0.672 0.167 0.201 0.248 0.191 0.537 0.587 0.551 ...
##  $ Age                     : int  50 31 32 21 30 26 30 34 51 31 ...
##  $ Outcome                 : int  1 0 1 0 0 1 0 1 1 1 ...
# Looking basics info of the attributes. 
summary(diabetes.cl)
##   Pregnancies        Glucose      BloodPressure    SkinThickness 
##  Min.   : 0.000   Min.   : 44.0   Min.   : 38.00   Min.   : 7.0  
##  1st Qu.: 1.000   1st Qu.: 99.0   1st Qu.: 64.00   1st Qu.:25.0  
##  Median : 3.000   Median :114.0   Median : 72.00   Median :29.0  
##  Mean   : 3.802   Mean   :119.1   Mean   : 72.09   Mean   :28.7  
##  3rd Qu.: 6.000   3rd Qu.:136.8   3rd Qu.: 80.00   3rd Qu.:32.0  
##  Max.   :13.000   Max.   :198.0   Max.   :106.00   Max.   :60.0  
##     Insulin           BMI        DiabetesPedigreeFunction      Age      
##  Min.   : 15.0   Min.   :18.20   Min.   :0.0780           Min.   :21.0  
##  1st Qu.:114.2   1st Qu.:27.30   1st Qu.:0.2395           1st Qu.:24.0  
##  Median :115.5   Median :32.00   Median :0.3595           Median :29.0  
##  Mean   :122.3   Mean   :31.98   Mean   :0.4252           Mean   :33.1  
##  3rd Qu.:120.0   3rd Qu.:36.00   3rd Qu.:0.5830           3rd Qu.:40.0  
##  Max.   :325.0   Max.   :49.70   Max.   :1.1620           Max.   :81.0  
##     Outcome      
##  Min.   :0.0000  
##  1st Qu.:0.0000  
##  Median :0.0000  
##  Mean   :0.3123  
##  3rd Qu.:1.0000  
##  Max.   :1.0000
# Looking a panoramic view of the data.
head(diabetes.cl)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35   115.5 33.6
## 2           1      85            66            29   115.5 26.6
## 3           8     183            64            29   115.5 23.3
## 4           1      89            66            23    94.0 28.1
## 6           5     116            74            29   115.5 25.6
## 7           3      78            50            32    88.0 31.0
##   DiabetesPedigreeFunction Age Outcome
## 1                    0.627  50       1
## 2                    0.351  31       0
## 3                    0.672  32       1
## 4                    0.167  21       0
## 6                    0.201  30       0
## 7                    0.248  26       1
# Percent of losted data.
perc <- 100 - nrow(diabetes.cl)/nrow(diabetes.raw)*100
cat("Porciento de datos perdiddos:", round(perc,2))
## Porciento de datos perdiddos: 15.36

Obtenemos una visión general de los datos una vez eliminados los outliers y sustituidos los missing values. Se puede apreciar que se ha prescindido de más de un 15% de los datos.

# Visual Analysis
visual_analy(diabetes.cl)

En la gráfica anterior se aprecia como han cambiado las disposiciones de las variables que tenían un número elevado de valores ausentes ( Insulin , SkinThickness ), presentando ahora todos los valores que se han sustituido por la mediana.

3.8 Análisis Exploratorio

En este apartado se procede a analizar las relaciones de cada una de las variables predictoras con la variable target, intentando encontrar patrones o comportamientos que puedan aportar cualquier información sobre el conjunto de datos. También se convertirán los valores de la variable Outcome a categóricos, esta tarea facilitará el posterior uso de la variable target a la hora de analizar las diferentes relaciones entre esta variable y las predictoras.

Para trabajar en el análisis exploratorio se crea una copia de los datos limpios.

# Create a copy of the cleaned dataset.
diabetes.exp <- diabetes.cl

diabetes.exp$Outcome[diabetes.exp$Outcome == 1] <- "Healthy"
diabetes.exp$Outcome[diabetes.exp$Outcome == 0] <- "Diabetic"

3.8.1 Análisis variable Age

library(ggplot2)

# Discretizing age variable
diabetes.exp["Age"] <- cut(diabetes.exp$Age, breaks=c(-Inf,23,35,55,+Inf),
                      labels=c("young","adults","mid-age","old"))


# Looking a panoramic view of the data.
head(diabetes.exp)
##   Pregnancies Glucose BloodPressure SkinThickness Insulin  BMI
## 1           6     148            72            35   115.5 33.6
## 2           1      85            66            29   115.5 26.6
## 3           8     183            64            29   115.5 23.3
## 4           1      89            66            23    94.0 28.1
## 6           5     116            74            29   115.5 25.6
## 7           3      78            50            32    88.0 31.0
##   DiabetesPedigreeFunction     Age  Outcome
## 1                    0.627 mid-age  Healthy
## 2                    0.351  adults Diabetic
## 3                    0.672  adults  Healthy
## 4                    0.167   young Diabetic
## 6                    0.201  adults Diabetic
## 7                    0.248  adults  Healthy
x <- table(diabetes.exp$Age,diabetes.exp$Outcome)/nrow(diabetes.exp) * 100
x
##          
##            Diabetic   Healthy
##   young   20.615385  2.615385
##   adults  29.846154 11.846154
##   mid-age 14.000000 14.769231
##   old      4.307692  2.000000
# Looking for appearances.
ggplot(data = diabetes.exp,aes(x=Age,fill=Outcome))+geom_bar(binwidth = 3,position="dodge")+ylab("Count") + xlab("Age")

Tal y como se puede apreciar en la gráfica, la mayoría de los casos tanto negativos como positivos se encuentran en las personas adultas y de mediana edad.

3.8.2 Análisis variable Pregnancies

# Looking for appearances.
ggplot(data = diabetes.exp,aes(x=Pregnancies,fill=Outcome))+geom_bar(binwidth = 3,position="dodge")+ylab("Count") + xlab("Pregnancies")

En la gráfica se aprecia que el las mujeres embarazadas tienen una mayor probabilidad de sufrir diabetes.

3.8.3 Análisis variable Glucose

En este apartado se intentará obtener alguna información de la variable Glucose con respecto a la Outcome. .

# Looking for appearances.

fig <- plot_ly(x = diabetes.exp$Glucose,
               color = diabetes.exp$Outcome,
               colors =  c("#F35E48", "#7CA6D7"),
               type = "histogram",
               xbins = data.frame(
                 start=min(diabetes.raw$Glucose)-1,
                 end=max(diabetes.raw$Glucose)+1,
                 size=5
                ))
fig

En esta gráfica se puede apreciar que la mayoría de casos con resultado positivo al examen de Diabetes tienen valores entre 90 y 120.

3.8.4 Análisis variable SkinThickness

# Looking for appearances.

fig <- plot_ly(x = diabetes.exp$SkinThickness,
               color = diabetes.exp$Outcome,
               colors =  c("#F35E48", "#7CA6D7"),
               type = "histogram",
               xbins = data.frame(
                 start=min(diabetes.exp$SkinThickness)-1,
                 end=max(diabetes.exp$SkinThickness)+1,
                 size=3
                ))
fig

3.8.5 Análisis variable Insulin

# Looking for appearances.

fig <- plot_ly(x = diabetes.exp$Insulin,
               color = diabetes.exp$Outcome,
               colors =  c("#F35E48", "#7CA6D7"),
               type = "histogram",
               xbins = data.frame(
                 start=min(diabetes.exp$Insulin)-1,
                 end=max(diabetes.exp$Insulin)+1,
                 size=15
                ))
fig

3.8.6 Análisis variable BMI

# Looking for appearances.

fig <- plot_ly(x = diabetes.exp$BMI,
               color = diabetes.exp$Outcome,
               colors =  c("#F35E48", "#7CA6D7"),
               type = "histogram",
               xbins = data.frame(
                 start=min(diabetes.exp$BMI)-1,
                 end=max(diabetes.exp$BMI)+1,
                 size=3
                ))
fig

Este análisis no muestra relevancias con respecto a la salida, ambas clases (diabéticos y no diabéticos).

3.8.7 Análisis variable DiabetesPedigreeFunction

# Looking for appearances.

fig <- plot_ly(x = diabetes.exp$DiabetesPedigreeFunction,
               color = diabetes.exp$Outcome,
               colors =  c("#F35E48", "#7CA6D7"),
               type = "histogram",
               xbins = data.frame(
                 start=min(diabetes.exp$DiabetesPedigreeFunction)-1,
                 end=max(diabetes.exp$DiabetesPedigreeFunction)+1,
                 size=0.5
                ))
fig

3.8.8 Análisis de Correlaciones y Distribuciones

En este apartado de pretende buscar las correlaciones entre cada una de las variables del dataset, tomándolas de dos a dos y construyendo la matriz de correlaciones. También se intentará identificar las diferentes distribuciones de estas gracias a sus histogramas.

Para facilitar esta tarea se usa una poderosa herramienta que permite ver ambas características a la vez, los pairs plots. En la diagonal principal de se muestran las distribuciones de las variables, en la mitad inferior se observan los gráficos de densidad y en la parte superior de la figura la matriz de correlación (se utiliza la correlación de pearson).

library(psych)

pairs.panels(diabetes.exp, 
             method = "pearson", # correlation method
             hist.col = "#00AFBB",
             density = TRUE,  # show density plots
             ellipses = TRUE # show correlation ellipses
)

3.8.9 Conclusiones del análisis exploratorio

De los resultados obtenidos en el análisis exploratorio se pueden obtener las siguientes conclusiones:

  • Las variables Glucose, BloodPressure y BMI, presentan una distribución normal.
  • Las variabels Pregnancies, Insulin , Age, DiabetesPedigreeFunction están sesgadas a la derecha ( skewed right).
  • No hay una correlación alta entre ninguno de los parámetros, aunque si se nota que hay cierta relación entre las siguientes variables; Pregnancies - Age, BloodPressure - Age y Insulin - Glucose.
  • Las variables más relacionadas con la variable target son Glucose y BMI, las demás presentan una correlación similar y la que menos influencia tiene sobre la variable clase es DiabetesPedigreeFunction.
  • Las mujeres entre adultas y de mediana edad son las más propensas a tener diabetes, teniendo un porcentaje de aproximadamente el 45% del total de casos registrados.
  • Las mujeres despúes de tener hijos son más propensas a padecer esta enfermedad.
  • Las personas con altos niveles de insulina, glucosa y tensión son más propensas también a padecer diabetes.

3.9 SVD (Singular Value Decomposition)

En este apartado se aplicará un proceso de SVD al dataset con el que se ha trabajado hasta el momento. El SVD es una de las más poderosas técnicas del Álgebra lineal utilizada para la reducción del tamaño y la dimensionalidad de los datos. Puede ser utilizada en la compresión de imágenes, en la reducción del ruido en los datos o en la elaboración de sistemas de recomendación, entre otras muchas aplicaciones. Las principales empresas tecnológicas de momento utilizan de alguna manera estas técnica, por ejemplo Netflix lo utiliza para sus sistema de recomendación de contenido multimedia, Amazon para recomendar sus productos y Facebook al sus sistemas de reconocimiento facial.

Esta técnica utiliza como base otra de los más utilizados procedimientos para la reducción de la dimensionalidad, PCA ( Principal Component Analysis) (Wikipedia contributors, 2020), solo que en lugar de buscar las características principales no correlacionadas en las variables originales, el SVD busca en ambas dimensiones, analizando tanto los registros como las características. A continuación de ofrece una reseña de los fundamentes matemáticos detrás de esta técnica y se aplica al conjunto de datos en cuestión.

3.9.1 Fundamentos matemáticos

La técnica de SVD consiste en reducir la matriz original \(A\)* con rank \(r\), en una matriz más pequeña con rank \(k\). Este método es aplicable tanto a matrices cuadradas como a rectangulares, y los valores de las matrices pueden ser reales o complejos, la única restricción es que tienen que ser numéricos ya que utilizan las correlaciones para realizar el análisis.

La reducción se realiza factorizando la matriz \(A\) de la forma \(m\)x\(n\) en la multiplicación de tres matrices, de la forma \(A= UΣV^{T}\).

Donde:

\(m\): La cantidad de variables de la base de datos.

\(n\): La cantidad de entradas en la base de datos.

\(U\): Matriz de tamaño \(m\)x\(p\) , cuyas columnas son el resultado de calcular los eigenvectors de la matriz de correlaciones \(AA^{T}\).

Esta matriz posee las siguientes características:

  • Es una matriz ortogonal, tal que (\(U^{T}U = UU^{T}=I\)).
  • En ocasiones se le nombra como left singular vector, y contienen información relacionada con las columnas de la matriz \(A\).
  • Las columnas de \(U\) son exactamente iguales a las columnas de \(A\), pero están jerárquicamente organizadas, de manera que estos eigenvectors describen la varianza de las columnas de \(A\).

\(Σ\): Matriz diagonal que contiene los valores singulares de \(r\), que son calculados como las raíces cuadradas de los eigeivalues distintos de cero de \(A^{T}A\) y \(AA^{T}\). Estos valores se pueden identificar como los niveles de la varianza (\(\sigma\)) de cada uno de los singular vectors.

Esta matriz tiene algunas características que le otorgan una gran importancia:

  • Los valores de \(\sigma\), (en la diagonal principal), están ordenados por importancia, con lo cual la carga de información útil en los primeros elementos será mayor que en los siguientes.
  • Independientemente que el tamaño de la matriz sea de \(p\)x\(p\) solo contiene \(n\) valores de \(\sigma > 0\), que corresponden a los \(m\).

\(V^{T}\): Es una matriz de tamaño \(p\)x\(n\) , cuyas columnas son el resultado de calcular los eigenvectors de la matriz de correlaciones \(A^{T}A\).

Esta matriz posee las siguientes características:

  • Es una matriz ortogonal, tal que (\(V^{T}V = VV^{T}=I\)).
  • En ocasiones se le nombra como right singular vectors y contiene infomración relacionada con las filas de la matriz \(A\).
  • Las columnas de \(V^{T}\) contienen información que relacionan las columnas de la matriz \(U\) con los valores de la matriz \(A\) escalados por los valores de \(\sigma\).

Ej: El vector \(v_2^{T}\) que corresponde a la segunda fila de la matriz \(V\), es una mezcla entre la segunda columna \(u_2\) de la matriz \(U\) y la segunda columna de la matriz \(A\), y como siempre escalado por el valor de la variable \(\sigma_2\).

3.9.2 Reducciión de la dimensionalidad

Una vez conocidos los principios matemáticos que rigen este procedimiento se puede proceder a aplicar la técnica SVD para reducir la dimensionalidad de los conjuntos de datos. Partiendo de la base de las características de las matrices \(U\), \(Σ\) y \(V^{T}\), que demuestran que los valores de estas matrices están ordenados por importancia, se seleccionarán solo los más importantes para que conformen el modelo final.

Con el objetivo de facilitar el análisis se propone un ejemplo con un conjunto de datos pequeño que contiene información de los ratings de películas para algunas personas.

# Create a matrix.
A = as.matrix(data.frame(c(4,7,-1,8), c(-5,-2,4,2), c(-1,3,-3,6)))

# Set the columns and rows names.
colnames(A) <- c("RamboII","Rocky IV","Harry Potter")
rownames(A) <- c("Bart","Michael","Tim","Sophie")

A
##         RamboII Rocky IV Harry Potter
## Bart          4       -5           -1
## Michael       7       -2            3
## Tim          -1        4           -3
## Sophie        8        2            6

En este ejemplo se utilizará la siguiente nomenclatura para identificar las diferentes matrices:

  • A: Matriz original (\(A\)).
  • U: Será la matriz de los left eigenvectors (\(U\)).
  • S: Será la matriz \(Σ\).
  • Vt: Será la matriz de los rigth eigenvectors (\(V^{T}\)).

Para obtener estas matrices solamente es necesario invocar la función svd() pasando como parámetro la matriz A. Una de las características más importante de este método es que el tamaño de la matriz \(S\) determinará el tamaño de las otras dos matrices, y este tamaño viene determinado por el rank de la matriz, que define la cantidad de filas y columnas linearmente independientes.

A continuación se calcula el valor el rank \(r\) y se aplica el método.

library(Matrix)

# Get the rank of A matrix.
r <- rankMatrix(A)
r[1]
## [1] 3
# Appliying SVD method to matrix A.
A.svd <- svd(A)

# Set the values to each matrix.
U <- A.svd$u
U
##            [,1]       [,2]        [,3]
## [1,] -0.2816569  0.7303849 -0.42412326
## [2,] -0.5912537  0.1463017 -0.18371213
## [3,]  0.2247823 -0.4040717 -0.88586638
## [4,] -0.7214994 -0.5309048  0.04012567
S <- A.svd$d
S
## [1] 13.161210  6.999892  3.432793
Vt <- A.svd$v
Vt
##            [,1]        [,2]       [,3]
## [1,] -0.8557101  0.01464091 -0.5172483
## [2,]  0.1555269 -0.94610374 -0.2840759
## [3,] -0.4935297 -0.32353262  0.8073135

En este punto del proceso ya se cuenta con la descomposición de la matriz original \(A\), y las matrices que la componen ya han sido calculadas, ahora es necesario realizar la reducción de la dimensionalidad, y para ello se utilizan los valores de los componentes de las matrices y el valor de \(r\).

Primero es necesario analizar como está compuesta la matriz \(A\).

\(A = \sigma_1u_1v_1^{T} + \sigma_2u_2v_2^{T} + ... \sigma_m*u_m*v_m^{T}\)

Es conocido que al estar ordenados por importancia los componentes, la cantidad de información relevante irá en descenso a medida que aumentan los valores de \(r\), por este motivo es necesario seleccionar un valor de \(r\) en el cual se corte la sumatoria anteriormente definida. De esta manera se reduce la dimensionalidad y se mantiene la mayoría de la información relevante del modelo.

En la siguiente figura la parte señalada en color rojo será la correspondiente a valores de \(r\) que no son seleccionados para formar parte del modelo. Este nuevo valor de \(r\) se denotará como \(k\).

De modo que el modelo quedaría con la siguiente esxtructura.

\(A= U_{mxk}Σ_{kxk}V_{kxn}^{T}\)

3.9.3 Elección de k

Para elegir el número adecuado vectores para que conformen el modelo y en consecuencia el valor de \(k\) es necesario fijarse en la energía que contiene el modelo. A continuación se analizan varios aspectos para lograr una correcta elección de \(k\).

La energía es igual a la suma de los cuadrados de los valores de la matriz \(Σ\).

\(e= \sigma_1^{2} +\sigma_2^{2}+...\sigma_m^{2}\)

El correcto valor de \(r\) debe ser el que contenga al menos el 90% de la energía, para determinarlo se eliminan los valores de \(Σ\) con mayor índice y se comprueba la energía del resto.

# Energy.
e_total <- 0 

# Total energy.
for (i in S){
  e_total <- e_total + i^2
}
e_total
## [1] 234
# Get the 90%.
e.90 <- 0.9*e_total
e.90
## [1] 210.6
e <- 0
# Energy with only 2 sigma values.
for (i in S[1:2]){
  e <- e + i^2
}

# Condition.
print(e > e.90)
## [1] TRUE

Como resultado del análisis anterior se puede seleccionar un valor de \(k = 2\), ya que con estos valores singulares el modelo contiene más del 90% de la energía. En este caso hay muy pocas oportunidades de elegir un valor adecuado, a medida que aumentan estos valores de \(r\) esta técnica aporta mayores beneficios. Otra manera muy útil de obtener este valor es gracias a la visualización de la energía acumulada y los valores de los singular values, pero en este caso como hay tan pocos valores de \(\sigma\) no se pueden apreciar bien las magnitudes.

3.9.4 Aplicación de SVD

En este apartado se aplicará el método de SVD al conjunto de datos Pima Indians Diabetes Database. Se seguirán los mismos pasos que los realizados con la matriz de prueba y se razonarán los resultados obtenidos. En este caso como se cuenta con todos los datos es conveniente aplicar la reducción al conjunto entero de los datos, para luego si fuese necesario dividirlo en testing y training o realizar alguna otra modificación, los datos estén comprimidos bajo los mismos parámetros.

El objetivo de este procedimiento es obtener las 3 matrices de menor tamaño, almacenarlas para luego poder reconstruir los datos a partir de ellas.

3.9.5 Obtención de la matriz original A

Primeramente antes de aplicar el método se escalan los datos usando el escalado a z, con media 0 y varianza 1, para que los datos estén todos en el mismo orden. Posteriormente se ordenan los elementos del dataset, este paso es opcional, pero a su vez sirve para comparar los resultados obtenidos luego de aplicar el proceso de SVD.

# Scale the data.
diabetes.cl[1:8] <- scale(diabetes.cl[1:8])

# Order the elements.
h <- hclust(dist(diabetes.cl[,c(1:8)]))

diabetes.ordered <- diabetes.cl[h$order, ]
head(diabetes.ordered)
##     Pregnancies   Glucose BloodPressure SkinThickness     Insulin      BMI
## 238 -1.17155684 2.0539008   1.583027871   -0.20282199 -0.13372769 1.895122
## 733 -0.55519752 1.8825667   1.406244413    0.99024854 -0.04495023 1.957664
## 682 -1.17155684 1.4713648   0.345543666    0.87094149 -0.13372769 2.755086
## 747 -0.86337718 0.9573624   1.936594786    1.46747676 -0.13372769 2.708179
## 379  0.06116181 1.2657638   0.257151937    0.03579212 -0.13372769 2.551822
## 236  0.06116181 1.7797662  -0.008023249    0.03579212 -0.13372769 1.816943
##     DiabetesPedigreeFunction         Age Outcome
## 238                1.0698738 -0.86264029       1
## 733                0.9057604 -0.77721735       1
## 682               -0.2512386 -0.60637146       1
## 747               -0.2758556 -0.52094852       1
## 379               -0.7681956 -0.09383382       1
## 236                0.2205873 -0.60637146       1

Una vez el se cuenta con el dataset ordenado se separa la variable objetivo del mismo y se almacena en la variable. Luego se calcula el rango de la matriz para saber tener una idea del formato del conjunto de datos, este valor indicará cuantas columnas y filas son linealmente independientes. Y para finalizar este paso se aplica el SVD a la matriz \(A\), que como resultado devuelve las tres matrices con las mismas nomenclaturas utilizadas anteriormente.

# Split the target variable.
Outcome = diabetes.ordered$Outcome

# Create the original matrix A.
A <- as.matrix(diabetes.ordered)


# Get the rank of A matrix.
r <- rankMatrix(A[,c(1:8)])
paste("rank:", r[1])
## [1] "rank: 8"
# Applying SVD method to matrix A.
A.svd <- svd(A[,c(1:8)])

# Set the values to each matrix.
U <- A.svd$u

S <- A.svd$d

Vt <- A.svd$v

3.9.6 Elección de k

Al igual que con el ejemplo es necesario conocer cual es el número optimo de \(k\) para reducir la dimensionalidad de nuestros datos. Del análisis del paso anterior se obtiene que el valor de rank es igual a 8, y de entre estos 8 valores de \(r\) se necesitan obtener los \(k\) valores que aporten el 90% de la información. Este valor determinará la dimensionalidad de las amtrices que se almacenarán al finalizar el proceso.

# Energy.
e_total <- 0 

# Total energy.
for (i in S){
  e_total <- e_total + i^2
}
paste("Total Energy:" ,e_total)
## [1] "Total Energy: 5192"
# Get the 90%.
e.90 <- 0.9*e_total
paste("90% of Energy:" ,e.90)
## [1] "90% of Energy: 4672.8"
e <- 0
# Energy with only 2 sigma values.
for (i in S[1:7]){
  e <- e + i^2
}

# Condition
paste("e > 90%:" ,e > e.90)
## [1] "e > 90%: TRUE"

El número óptimo de \(k\) es 7, ya que con los 7 primeros valores de \(\sigma\) se explican más del 90% de los datos. Otro mecanismo muy utilizado para encontrar el número óptimo de \(k\) es graficando su energía.

# Total value of S square.
all_sing_sq <- sum(S^2)


# Percent vales per element of S.
perc_vec <- NULL
for (i in 1:length(S)) {
  perc_vec[i] <- sum(S[1:i]^2) / all_sing_sq
}


# Plot the energy.
plot(perc_vec, pch=20, col = "blue", cex = 1.5, xlab='Singular Value', ylab='% of Sum of Squares of Singular Values', main = "Choosing k for Dimensionality Reduction")
lines(x = c(0,100), y = c(.90, .90))

Se puede apreciar en la gráfica que la línea que indica el 90% está justo pisando el valor de \(\sigma = 6\), pero se selecciona 7 como valor óptimo de \(k\) para asegurarnos que se cumple con la condición.

# Set the k value.
k <- 7

Con este valor de k ya se pueden conformar las matrices \(U\), \(Σ\) y \(V^{T}\) definitivas, las cuales tendrán como prefijo a su nomenclatura normal los caracteres “diab_”.

# Set the final values.
diab_U <- U[,1:k]

diab_S <- S[1:k]

diab_Vt <- Vt[,1:k]

Estas matrices junto con la variable Outcome serán los valores que se almacenarán para posteriormente reconstruir el modelo.

Como paso final y a modo de comprobación, se procede a reconstruir la matriz \(A\) a partir de sus descomposiciones almacenadas, se establece el valor e \(k = r\) y se comprueba que se obtiene la matriz original.

diabetes.svd <- U %*% diag(S) %*% t(Vt)

# Check the equality.
head(diabetes.svd)
##             [,1]      [,2]         [,3]        [,4]        [,5]     [,6]
## [1,] -1.17155684 2.0539008  1.583027871 -0.20282199 -0.13372769 1.895122
## [2,] -0.55519752 1.8825667  1.406244413  0.99024854 -0.04495023 1.957664
## [3,] -1.17155684 1.4713648  0.345543666  0.87094149 -0.13372769 2.755086
## [4,] -0.86337718 0.9573624  1.936594786  1.46747676 -0.13372769 2.708179
## [5,]  0.06116181 1.2657638  0.257151937  0.03579212 -0.13372769 2.551822
## [6,]  0.06116181 1.7797662 -0.008023249  0.03579212 -0.13372769 1.816943
##            [,7]        [,8]
## [1,]  1.0698738 -0.86264029
## [2,]  0.9057604 -0.77721735
## [3,] -0.2512386 -0.60637146
## [4,] -0.2758556 -0.52094852
## [5,] -0.7681956 -0.09383382
## [6,]  0.2205873 -0.60637146
head(diabetes.ordered)
##     Pregnancies   Glucose BloodPressure SkinThickness     Insulin      BMI
## 238 -1.17155684 2.0539008   1.583027871   -0.20282199 -0.13372769 1.895122
## 733 -0.55519752 1.8825667   1.406244413    0.99024854 -0.04495023 1.957664
## 682 -1.17155684 1.4713648   0.345543666    0.87094149 -0.13372769 2.755086
## 747 -0.86337718 0.9573624   1.936594786    1.46747676 -0.13372769 2.708179
## 379  0.06116181 1.2657638   0.257151937    0.03579212 -0.13372769 2.551822
## 236  0.06116181 1.7797662  -0.008023249    0.03579212 -0.13372769 1.816943
##     DiabetesPedigreeFunction         Age Outcome
## 238                1.0698738 -0.86264029       1
## 733                0.9057604 -0.77721735       1
## 682               -0.2512386 -0.60637146       1
## 747               -0.2758556 -0.52094852       1
## 379               -0.7681956 -0.09383382       1
## 236                0.2205873 -0.60637146       1

3.10 Conclusiones

En esta práctica se ha recorrido la primera parte de un proyecto de minería de datos, correspondiente a los procesos de limpieza y preparación de los datos. Se ha seleccionado un dataset de un repositorio de datos abiertos y se ha acondicionado para cumplir con las necesidades de la práctica. Se ha realizado el tratamiento tanto de los valores extremos como de los valores ausentes. Igualmente se ha realizado un análisis exploratorio de los datos para intentar observas sus principales comportamientos respecto a la variable objetivo.

Todos estos pasos sirvieron de premisa para al final de la práctica aplicar el método de Descomposición en Valores Singulares, método que supuso todo un reto porque fue investigado de manera autodidacta. Con la aplicación del mismo se consiguió afianzar los conocimientos adquiridos durante la investigación, demostrando la importancia de este para proyectos reales de minería de datos. Es una lástima que los datos no pudiesen ser reducidos un poco más, debido a que sus variables presentaban muy poca correlación y eran pocas, pero aún así pude asimilar el potencial de este método. De manera análoga tuve que consultar información acerca de PCA, que aunque no se haya implementado en esta práctica, he fijado los conocimientos básicos de este método.


4 Rúbrica



5 Recursos de programación




6 Bibliografía

Material de la asignatura Minería de Datos. Canal de Youtube de Steven Brunton Profesor de la Universidad de Washington

Wikipedia contributors. (2020). PCA — Wikipedia, the free encyclopedia. https://es.wikipedia.org/wiki/An%C3%A1lisis_de_componentes_principales